package com.kx.smartdevice.service.impl;

import com.kx.smartdevice.cache.CategoriesCache;
import com.kx.smartdevice.constants.ResultCode;
import com.kx.smartdevice.event.CategoryChangeEvent;
import com.kx.smartdevice.exceptions.AddErrorException;
import com.kx.smartdevice.exceptions.DeleteErrorException;
import com.kx.smartdevice.exceptions.QueryErrorException;
import com.kx.smartdevice.mapper.CategoryMapper;
import com.kx.smartdevice.pojo.Category;
import com.kx.smartdevice.service.CategoryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Set;

/**
 * @ClassName CategoryImpl
 * @Author Sun
 * @Date 2021/5/27 21:50
 */
@Service
@Transactional
public class CategoryServiceImpl implements CategoryService {
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private CategoriesCache categoriesCache;
    @Autowired
    private ApplicationContext context;//发布事件的

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Set<Category> findAllCategories() {
        Set<Category> categorySet = categoriesCache.getAllData();//先查询缓存,第一次一定是没有的,但是我们在缓存中直接创建了一个 set 所以一开始长度是 0
//        if (categorySet == null||categorySet.size()==0) { //一开始我们判断 0 的时候查询数据库是担心万一缓存没查询,但是我们可以确定缓存只要启动就一定查询,如果长度还是 0 说明数据库中根本没有数据,就没有必要查询数据了
        if (categorySet == null) {//缓存中没有数据时在查询数据库
            return categoryMapper.findAllCategories();
        }
        return categorySet;
    }

    //根据主键查询单个数据，就是从map缓存中获取数据
    @Override
    public Category getCategoryById(Long id) {
        if (id == null||id<=0) {
            return null;
        }
        //直接从缓存中返回
        Category category = categoriesCache.get(id);
        if(category==null){
            //缓存中数据不存在
            throw new QueryErrorException("数据不存在请检查后再试", ResultCode.DATA_NOT_EXIST);
        }
        return category;
        //TODO 如果缓存中是没有的,返回 null,理论上来说我们的缓存一定是加载成功的,所以缓存返回 null 就代表没有
        //为了保证健壮性,我们可以去查询一下数据库,查询完成后保存到缓存中,也就是缓存需要提供一个添加的方法,让我们可以添加单个数据到缓存
        //但是上面的操作会发生一个问题,缓存穿透--->缓存中没有数据,数据库也没有,会导致每次查询都流向数据库,数据库 tmd 又崩溃的
    }


    @Override
    public void addCategory(Category category) {
        if (category == null||category.isEmpty()) {
            throw new AddErrorException("数据为空", ResultCode.NULL_DATA);
        }

        categoryMapper.addCategory(category);
        //更新缓存
        //context.publishEvent(CategoryChangeEvent.class);
        context.publishEvent(new CategoryChangeEvent());

    }

    @Override
    public int deleteCategory(String[] ids) {
        if (ids.length==0) {
            throw new DeleteErrorException("用户id没有传递", ResultCode.DATA_NOT_ALLOWED);
        }
        int result = categoryMapper.deleteCategory(ids);

        //更新缓存数据
        context.publishEvent(new CategoryChangeEvent());
        return result;
    }

    @Override
    public int updateCategory(Category category) {
        if (category == null) {
            throw new DeleteErrorException("没有传递数据", ResultCode.NULL_DATA);
        }
        int result  = categoryMapper.updateCategory(category);
        //更新缓存数据
        context.publishEvent(new CategoryChangeEvent());
        return result;
    }
}
